package com.reactive.springbootreactive.config;

import com.reactive.springbootreactive.config.security.AccessDeniedHandlerMy;
import com.reactive.springbootreactive.config.security.AuthenticationEntryPointMy;
import com.reactive.springbootreactive.config.security.ReactiveAuthenticationManagerMy;
import com.reactive.springbootreactive.config.security.ServerSecurityContextRepositoryMy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.server.ServerWebExchange;

@EnableReactiveMethodSecurity
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
        ReactiveAuthenticationManagerMy reactiveAuthenticationManagerMy = new ReactiveAuthenticationManagerMy();
        ServerSecurityContextRepositoryMy serverSecurityContextRepositoryMy = new ServerSecurityContextRepositoryMy();
        return httpSecurity.csrf().disable()
                .cors().configurationSource(new MyCorsConfigurationSource())
                .and()
                .exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPointMy())
                .accessDeniedHandler(new AccessDeniedHandlerMy())
                .and().authenticationManager(reactiveAuthenticationManagerMy)
                .securityContextRepository(serverSecurityContextRepositoryMy)
                .authorizeExchange()
                .pathMatchers("/auth/**").permitAll()
                .pathMatchers(HttpMethod.OPTIONS).permitAll()
                .anyExchange().authenticated()
//                .and().formLogin(Customizer.withDefaults())
                .and()
                //httpBasic 是http最基本的认证方式，现在已经不太用了
//                .httpBasic(httpBasic -> httpBasic/* used for authenticating the credentials*/.authenticationManager(reactiveAuthenticationManagerMy)/* Custom persistence of the authentication*/.securityContextRepository(serverSecurityContextRepositoryMy))
                .build();
//                .and().build();
    }

    private static class MyCorsConfigurationSource implements CorsConfigurationSource {
        @Override
        public CorsConfiguration getCorsConfiguration(ServerWebExchange exchange) {
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.setAllowCredentials(true);
            corsConfiguration.addAllowedOrigin("*");
            corsConfiguration.addAllowedHeader("*");
            corsConfiguration.addAllowedMethod("*");
            UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
            urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
            return corsConfiguration;
        }
    }
}
